﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using CCWin;
using System.Threading;
using System.Windows.Forms.DataVisualization.Charting;

namespace SCCM
{
    public partial class NewMainWindow : Skin_Mac
    {
        //chart 数据容器
        List<String> x = new List<string>(65);
        List<double> yNO2 = new List<double>(65);
        List<double> yNO = new List<double>(65);
        List<double> yCO = new List<double>(65);
        List<double> yO3 = new List<double>(65);
        List<double> yTem = new List<double>(65);
        List<double> yRH = new List<double>(65);
        List<double> yAto = new List<double>(65);

        //串口部分使用
        private SerialPort comm = new SerialPort();
        private SerialPort comm1 = new SerialPort();
        private StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建，定义到外面。
        private StringBuilder builder1 = new StringBuilder();
        private DataItem newDataItem = new DataItem();//每次接收一次数据，封装在该Item中

        private int id;
        private double NO2Limit = 20;
        private double COLimit = 20;
        private double NOLimit = 20;
        private double O3Limit = 20;


        public NewMainWindow()
        {
            InitializeComponent();
        }

        private void NewMainWindow_Load(object sender, EventArgs e)
        {
            //初始化警报阈值
            DataBase db = new DataBase();
            DataTable dt = db.SelectLimits();
            if (dt.Rows.Count == 0)
                return;
            id = (int)dt.Rows[0]["id"];
            NO2Limit = (double)dt.Rows[0]["NO2"];
            COLimit = (double)dt.Rows[0]["CO"];
            NOLimit = (double)dt.Rows[0]["NO"];
            O3Limit = (double)dt.Rows[0]["O3"];

            InitChart();
            //显示时钟
            timer2.Start();
            timer2.Interval = 1000;

            //初始化下拉串口名称列表框
            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            comboPortName.Items.AddRange(ports);
            comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;

            //初始化串口
            initComm();
        }

        private void initComm()
        {
            //添加事件注册

            comm.BaudRate = 115200;//9600;
            comm.DataBits = 8;
            comm.NewLine = "\n";
            comm.Parity = Parity.None;
            comm.StopBits = StopBits.One;
            comm.ReceivedBytesThreshold = 64;
            comm.DataReceived += CommDataReceived;


            comm1.BaudRate = 115200;//9600;
            comm1.DataBits = 8;
            comm1.NewLine = "\n";
            comm1.Parity = Parity.None;
            comm1.StopBits = StopBits.One;
            comm1.ReceivedBytesThreshold = 64;
            comm1.DataReceived += CommDataReceived1;
        }
        //第一个串口接受函数
        void CommDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = comm.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
            comm.Read(buf, 0, n);//读取缓冲数据

            //直接按ASCII规则转换成字符串
            builder.Append(Encoding.GetEncoding("GBK").GetString(buf));

            //2015-01-18 16:33\n变电站:000;开关室:000;开关柜:000;NO2: 0.00;CO: 0.00;NO: 0.01;O3: 0.00;Tem:11.0C;RH:42.0%;Ato:100.8kPa;
            //MessageBox.Show(newDataItem.ToString());
            //string temp = "2015-01-18 16:33\n变电站:000;开关室:000;开关柜:000;NO2: 0.00;CO: 0.00;NO: 0.01;O3: 0.00;Tem:11.0C;RH:42.0%;Ato:100.8kPa;";
            //builder.Append(Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(temp)));
            string recvString = builder.ToString();
            //MessageBox.Show(recvString);
            new Thread(processUI).Start(recvString);

            builder.Remove(0, builder.Length);//清除字符串构造器的内容
        }
        //第一个串口数据处理
        public void processUI(object recv)
        {
            string recvString = recv as string;
            //MessageBox.Show(recvString);
            String[] tks = recvString.Split('\n');


            try
            {
                newDataItem.Datetime = tks[0];

                string[] tks1 = tks[1].Split(';');
                newDataItem.Bdzbh = tks1[0].Split(':')[1];
                newDataItem.Kgsbh = tks1[1].Split(':')[1];
                newDataItem.Kggbh0 = tks1[2].Split(':')[1];
                newDataItem.NO2 = ExtractNumber(tks1[3].Split(':')[1]);
                newDataItem.CO = ExtractNumber(tks1[4].Split(':')[1]);
                newDataItem.NO = ExtractNumber(tks1[5].Split(':')[1]);
                newDataItem.O3 = ExtractNumber(tks1[6].Split(':')[1]);
                newDataItem.Tem = ExtractNumber(tks1[7].Split(':')[1]);
                newDataItem.RH = ExtractNumber(tks1[8].Split(':')[1]) / 100;
                newDataItem.Ato = ExtractNumber(tks1[9].Split(':')[1]);
                //因为要访问ui资源，所以需要使用invoke方式同步ui。
                this.Invoke((EventHandler)(delegate
                {
                    StatusLineInfo("接收到数据: " + tks[0] + ";" + tks[1], false);
                    DataHandler(newDataItem, 0);
                }));
            }
            catch
            {
                StatusLineInfo("上传格式出错.请调整上传模式.", true);
            }

        }
        //第二个串口接受函数
        void CommDataReceived1(object sender, SerialDataReceivedEventArgs e)
        {
            int n = comm1.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
            comm1.Read(buf, 0, n);//读取缓冲数据
            //comm.cl




            //直接按ASCII规则转换成字符串
            builder1.Append(Encoding.GetEncoding("GBK").GetString(buf));

            string recvString = builder1.ToString();
            //接收到最后一组
            if (recvString.Contains("none"))
            {
                //MessageBox.Show(recvString);
                new Thread(processUI1).Start(recvString);
                builder1.Remove(0, builder1.Length);//清除字符串构造器的内容
            }
        }

        public void processUI1(object recv)
        {
            //多组数据
            string recvString = recv as string;
            //MessageBox.Show(recvString);
            String[] tks = recvString.Split('\n');

            int size = (tks.Length - 1) / 2;

            for (int i = 0; i < size; i++)
            {
                try
                {
                    newDataItem.Datetime = tks[2 * i];

                    string[] tks1 = tks[2 * i + 1].Split(';');
                    newDataItem.Bdzbh = tks1[0].Split(':')[1];
                    newDataItem.Kgsbh = tks1[1].Split(':')[1];
                    newDataItem.Kggbh0 = tks1[2].Split(':')[1];
                    newDataItem.NO2 = ExtractNumber(tks1[3].Split(':')[1]);
                    newDataItem.CO = ExtractNumber(tks1[4].Split(':')[1]);
                    newDataItem.NO = ExtractNumber(tks1[5].Split(':')[1]);
                    newDataItem.O3 = ExtractNumber(tks1[6].Split(':')[1]);
                    newDataItem.Tem = ExtractNumber(tks1[7].Split(':')[1]);
                    newDataItem.RH = ExtractNumber(tks1[8].Split(':')[1]) / 100;
                    newDataItem.Ato = ExtractNumber(tks1[9].Split(':')[1]);
                    //因为要访问ui资源，所以需要使用invoke方式同步ui。
                    this.Invoke((EventHandler)(delegate
                    {
                        StatusLineInfo("接收到数据: " + tks[0] + ";" + tks[1], false);
                        DataHandler(newDataItem, 1);
                    }));
                }
                catch
                {
                    StatusLineInfo("上传格式出错.请调整上传模式.", true);
                }
            }
        }

        private double ExtractNumber(string str)
        {

            string num = "";
            foreach (char c in str)
            {

                if ((c >= '0' && c <= '9' || c == '.'))
                    num += c;
            }
            return Convert.ToDouble(num);
        }
        /**
        * 初始化7个指标chart的显示的样式
        */
        public void InitChart()
        {
            //NO2Chart.ChartAreas[0].AxisX.IntervalType ;
            Color charLineColor = Color.Red;
            int charLineWidth = 2;
            Color charBackColor = Color.White;
            Color labelColor = Color.Green;
            int labelWidth = 2;

            NO2Chart.ChartAreas[0].AxisX.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            NO2Chart.ChartAreas[0].AxisY.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            NO2Chart.ChartAreas[0].AxisY.Interval = 5.000;
            NO2Chart.ChartAreas[0].AxisY.Minimum = 0.000;
            NO2Chart.ChartAreas[0].AxisY.Maximum = 20.000;
            NO2Chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            NO2Chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            NO2Chart.ChartAreas[0].AxisX.ScaleView.Position = 1;
            NO2Chart.ChartAreas[0].AxisX.ScaleView.Size = 10;
            NO2Chart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = System.Drawing.Color.Silver;
            NO2Chart.ChartAreas[0].AxisX.ScrollBar.LineColor = System.Drawing.Color.Black;
            NO2Chart.ChartAreas[0].BackColor = charBackColor;
            NO2Chart.Series[0].Color = charLineColor;
            NO2Chart.Series[0].BorderWidth = charLineWidth;
            NO2Chart.Series[0].IsValueShownAsLabel = true;
            NO2Chart.Series[0].LabelForeColor = labelColor;
            NO2Chart.Series[0].LabelBorderWidth = labelWidth;


            //--------------------------------------------------------------
            COChart.ChartAreas[0].AxisX.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            COChart.ChartAreas[0].AxisY.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            COChart.ChartAreas[0].AxisY.Interval = 10.000;
            COChart.ChartAreas[0].AxisY.Minimum = 0.000;
            COChart.ChartAreas[0].AxisY.Maximum = 50.000;
            COChart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            COChart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            COChart.ChartAreas[0].AxisX.ScaleView.Position = 1;
            COChart.ChartAreas[0].AxisX.ScaleView.Size = 10;
            COChart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = System.Drawing.Color.Silver;
            COChart.ChartAreas[0].AxisX.ScrollBar.LineColor = System.Drawing.Color.Black;
            COChart.ChartAreas[0].BackColor = charBackColor;
            COChart.Series[0].Color = charLineColor;
            COChart.Series[0].BorderWidth = charLineWidth;
            COChart.Series[0].IsValueShownAsLabel = true;
            COChart.Series[0].LabelForeColor = labelColor;
            COChart.Series[0].LabelBorderWidth = labelWidth;
            //--------------------------------------------------------------
            NOChart.ChartAreas[0].AxisX.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            NOChart.ChartAreas[0].AxisY.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            NOChart.ChartAreas[0].AxisY.Interval = 5.000;
            NOChart.ChartAreas[0].AxisY.Minimum = 0.000;
            NOChart.ChartAreas[0].AxisY.Maximum = 20.000;
            NOChart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            NOChart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            NOChart.ChartAreas[0].AxisX.ScaleView.Position = 1;
            NOChart.ChartAreas[0].AxisX.ScaleView.Size = 10;
            NOChart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = System.Drawing.Color.Silver;
            NOChart.ChartAreas[0].AxisX.ScrollBar.LineColor = System.Drawing.Color.Black;
            NOChart.ChartAreas[0].BackColor = charBackColor;
            NOChart.Series[0].Color = charLineColor;
            NOChart.Series[0].BorderWidth = charLineWidth;
            NOChart.Series[0].IsValueShownAsLabel = true;
            NOChart.Series[0].LabelForeColor = labelColor;
            NOChart.Series[0].LabelBorderWidth = labelWidth;
            //--------------------------------------------------------------
            O3Chart.ChartAreas[0].AxisX.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            O3Chart.ChartAreas[0].AxisY.LabelStyle.Font = new System.Drawing.Font("Tahoma", 7);
            O3Chart.ChartAreas[0].AxisY.Interval = 5.000;
            O3Chart.ChartAreas[0].AxisY.Minimum = 0.000;
            O3Chart.ChartAreas[0].AxisY.Maximum = 20.000;
            O3Chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
            O3Chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
            O3Chart.ChartAreas[0].AxisX.ScaleView.Position = 1;
            O3Chart.ChartAreas[0].AxisX.ScaleView.Size = 10;
            O3Chart.ChartAreas[0].AxisX.ScrollBar.ButtonColor = System.Drawing.Color.Silver;
            O3Chart.ChartAreas[0].AxisX.ScrollBar.LineColor = System.Drawing.Color.Black;
            O3Chart.ChartAreas[0].BackColor = charBackColor;
            O3Chart.Series[0].Color = charLineColor;
            O3Chart.Series[0].BorderWidth = charLineWidth;
            O3Chart.Series[0].IsValueShownAsLabel = true;
            O3Chart.Series[0].LabelForeColor = labelColor;
            O3Chart.Series[0].LabelBorderWidth = labelWidth;
        }

        public void updateData(Chart chart)
        {

            switch (chart.Name)
            {
                case "NO2Chart":
                    //reset();
                    chart.Series[0].Points.DataBindXY(x, yNO2);
                    NO2Chart.ChartAreas[0].AxisX.ScaleView.Scroll(ScrollType.Last);
                    break;
                case "NOChart":
                    chart.Series[0].Points.DataBindXY(x, yNO);
                    NOChart.ChartAreas[0].AxisX.ScaleView.Scroll(ScrollType.Last);
                    break;
                case "COChart":
                    chart.Series[0].Points.DataBindXY(x, yCO);
                    COChart.ChartAreas[0].AxisX.ScaleView.Scroll(ScrollType.Last);
                    break;
                case "O3Chart":
                    chart.Series[0].Points.DataBindXY(x, yO3);
                    O3Chart.ChartAreas[0].AxisX.ScaleView.Scroll(ScrollType.Last);
                    break;
            }

        }
        //timer1
        private void timer1_Tick(object sender, EventArgs e)
        {
            MoNiShuJuFaSong();
        }
        public void MoNiShuJuFaSong()
        {
            DateTime dt2 = DateTime.Now;
            //double[] valTypeDate = new double[7];
            //valTypeDate[0] = NextDouble(0.001, 0.005);
            //valTypeDate[1] = NextDouble(0.001, 0.005);
            //valTypeDate[2] = NextDouble(0.001, 0.008);
            //valTypeDate[3] = NextDouble(-0.005, 0.005);
            //valTypeDate[4] = NextDouble(-10, 50);
            //valTypeDate[5] = NextDouble(0.00, 1);
            //valTypeDate[6] = NextDouble(99, 120);
            newDataItem.Datetime = "2016-02-22 12:12";// dt2.ToString("yyyy-MM-dd HH:mm:ss");
            newDataItem.Bdzbh = "002";
            newDataItem.Kgsbh = "003";
            newDataItem.Kggbh0 = "005";
            newDataItem.NO2 = NextDouble(0.000, 20.000);
            newDataItem.CO = NextDouble(0.000, 50.000);
            newDataItem.NO = NextDouble(0.000, 20.000);
            newDataItem.O3 = NextDouble(0.000, 20.000);
            newDataItem.Tem = NextDouble(-10, 50);
            newDataItem.RH = NextDouble(0.00, 1);
            newDataItem.Ato = NextDouble(99, 120);
            DataHandler(newDataItem, 1);
        }
        public static double NextDouble(double miniDouble, double maxiDouble)
        {
            Random random = new Random();
            if (random != null)
            {
                return random.NextDouble() * (maxiDouble - miniDouble) + miniDouble;
            }
            else
            {
                return 0.0d;
            }
        }
        //报警弹框
        public void playAlertMusic(char[] flags)
        { 
            MusicForm m = new MusicForm(newDataItem.MyCopy(), flags);
            m.Show();

        }
        /**
         * 处理结束的数据
         * @param val:其他的7个参数值
         */
        public void DataHandler(DataItem val, int m)
        {
            if (O3InputCheckBox.Checked == true) {
                O3InputWindow window = new O3InputWindow(newDataItem);
                window.ShowDialog();
            }

            char[] flags = new char[4];

            if (newDataItem.NO2 >= NO2Limit)
                flags[0] = '1';
            else
                flags[0] = '0';

            if (newDataItem.CO >= COLimit)
                flags[1] = '1';
            else
                flags[1] = '0';

            if (newDataItem.NO >= NOLimit)
                flags[2] = '1';
            else
                flags[2] = '0';

            if (newDataItem.O3 >= O3Limit)
                flags[3] = '1';
            else
                flags[3] = '0';

            if (!new String(flags).Equals("0000"))
                this.playAlertMusic(flags);

            DataBase dataBase = new DataBase();

            string[] names = dataBase.getNamesByNumbers(val.Bdzbh, val.Kgsbh, val.Kggbh0);

            if (names != null)
            {
                bdzTextBox.Text = names[0];
                kgsTextBox.Text = names[1];
                kggTextBox.Text = names[2];
            }
            else {
                StatusLineInfo("无法找到匹配的开关柜", true);
                return;
            }

            string bdz = bdzTextBox.Text;
            string kgs = kgsTextBox.Text;
            string kgg = kggTextBox.Text;
            dataBase.Insert(val.Datetime, val.NO2, val.CO, val.NO, val.O3, val.Tem, val.RH, val.Ato, bdz, kgs, kgg, m);
            x.Add(val.Datetime.Replace(" ", "\n").Substring(2));
            if (x.Count > 60)
            {
                x.RemoveAt(0);
            }



            yNO2.Add(val.NO2);
            if (yNO2.Count > 60)
            {
                yNO2.RemoveAt(0);
            }
            updateData(NO2Chart);

            yCO.Add(val.CO);
            if (yCO.Count > 60)
            {
                yCO.RemoveAt(0);
            }
            updateData(COChart);

            yNO.Add(val.NO);
            if (yNO.Count > 60)
                yNO.RemoveAt(0);
            updateData(NOChart);

            yO3.Add(val.O3);
            if (yO3.Count > 60)
                yO3.RemoveAt(0);
            updateData(O3Chart);

        }
        //时钟滴答
        private void timer2_Tick(object sender, EventArgs e)
        {
            label5.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void StatusLineInfo(string info, bool isWarn)
        {
            if (isWarn)
                statusLine.ForeColor = Color.Red;
            else
                statusLine.ForeColor = Color.Green;

            statusLine.Text = info;
        }
        //结束按钮
        private void jieShu_Click(object sender, EventArgs e)
        {
            if (comm.IsOpen)
            {
                comm.Close();
                StatusLineInfo("已关闭串口，停止接受数据.", false);
                onLine.Enabled = true;
                offline.Enabled = true;
                onLinePic.Visible = false;
                offlinePic.Visible = false;

            }
            else {
                StatusLineInfo("串口关闭", false);
            }

            if (comm1.IsOpen)
            {
                comm1.Close();
                StatusLineInfo("已关闭串口，停止接受数据.", false);
                onLine.Enabled = true;
                offline.Enabled = true;
                onLinePic.Visible = false;
                offlinePic.Visible = false;

            }
            else
            {
                StatusLineInfo("串口关闭", false);
            }
            //timer1.Stop();
        }

        private void NewMainWindow_SizeChanged(object sender, EventArgs e)
        {
            int pwidth = Convert.ToInt32(zhiBiaoContainer.Width * 0.98);
            int height = Convert.ToInt32(zhiBiaoContainer.Height * 0.90);
            NO2GroupBox.Width = pwidth / 2;
            COGroupBox.Left = NO2GroupBox.Width + Convert.ToInt32(0.02 * zhiBiaoContainer.Width);
            COGroupBox.Width = pwidth / 2;

            O3GroupBox.Width = pwidth / 2;
            NOGroupBox.Left = pwidth / 2 + Convert.ToInt32(0.02 * zhiBiaoContainer.Width);
            NOGroupBox.Width = pwidth / 2;

            int subx = Convert.ToInt32((COGroupBox.Right - NO2GroupBox.Left) * 0.98);


            NO2GroupBox.Height = height / 2;
            COGroupBox.Height = height / 2;

            O3GroupBox.Top = NOGroupBox.Top = NO2GroupBox.Bottom + Convert.ToInt32(zhiBiaoContainer.Height * 0.02);
            O3GroupBox.Height = NOGroupBox.Height = height / 2;

            //时间label
            label5.Left = caoZuoContainer.Width - 165;
            label5.Top = caoZuoContainer.Top;
        }

        private void liShiShuju_Click(object sender, EventArgs e)
        {
            HistoryWindow history = new HistoryWindow();
            history.Show();
        }

        private void onLine_Click(object sender, EventArgs e)
        {
            //CommDataReceived(null,null);
            //if (bianDianZhan.Text.Trim().Equals("") || kaiGuanShi.Text.Trim().Equals("") || kaiGuanGui.Text.Trim().Equals(""))
            //{
            //    MessageBox.Show("请输入相关操作信息.");
            //    return;
            //}
            if (comboPortName.Text.Equals(""))
            {
                statusLine.Text = "请选择串口.";
                statusLine.ForeColor = Color.Red;
                return;
            }

            if (!comm.IsOpen)
            {

                try
                {
                    comm.PortName = comboPortName.Text;
                    //MessageBox.Show(comm.PortName);
                    comm.Open();
                    StatusLineInfo("串口已打开，等待数据...", false);
                    onLine.Enabled = false;
                    offline.Enabled = false;
                    onLinePic.Visible = true;
                    offlinePic.Visible = false;
                    //MessageBox.Show("开始收集数据");
                }
                catch (Exception ex)
                {
                    comm = new SerialPort();
                    initComm();
                    StatusLineInfo("串口已打开失败，请重试", true);
                }
            }
            else {
                StatusLineInfo("串口已打开", false);
            }
        }

        private void offline_Click(object sender, EventArgs e)
        {
            //timer1.Start();
            //timer1.Interval = 2000;
            //CommDataReceived(null,null);
            //if (bianDianZhan.Text.Trim().Equals("") || kaiGuanShi.Text.Trim().Equals("") || kaiGuanGui.Text.Trim().Equals(""))
            //{
            //    MessageBox.Show("请输入相关操作信息.");
            //    return;
            //}
            if (comboPortName.Text.Equals(""))
            {
                statusLine.Text = "请选择串口.";
                statusLine.ForeColor = Color.Red;
                return;
            }

            if (!comm1.IsOpen)
            {

                try
                {
                    comm1.PortName = comboPortName.Text;
                    //MessageBox.Show(comm.PortName);
                    comm1.Open();
                    StatusLineInfo("串口已打开，等待数据...", false);
                    comm1.Write("ZXSJ");
                    onLine.Enabled = false;
                    offline.Enabled = false;
                    onLinePic.Visible = false;
                    offlinePic.Visible = true;
                    //MessageBox.Show("开始收集数据");
                }
                catch (Exception ex)
                {
                    comm1 = new SerialPort();
                    initComm();
                    StatusLineInfo("串口已打开失败，请重试", true);
                }
            }
            else {
                StatusLineInfo("串口已打开", false);
            }
        }
    }
}
